package org.xx.armory.swing.components;

import javax.swing.*;
import java.awt.Dimension;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;

import static javax.swing.BorderFactory.createEmptyBorder;
import static org.xx.armory.commons.Validators.notNull;
import static org.xx.armory.commons.Validators.validIndex;
import static org.xx.armory.swing.ComponentUtils.combineBorders;

/**
 * 状态栏。
 */
public final class StatusBar
        extends JPanel {
    private List<StatusPane> statusPanes;

    public StatusBar() {
        initUi();
        this.statusPanes = new ArrayList<>();
    }

    protected void initUi() {
        final BoxLayout layout = new BoxLayout(this, BoxLayout.X_AXIS);
        this.setLayout(layout);

        setBorder(createEmptyBorder(2, 2, 2, 2));
    }

    /**
     * 向状态栏中加入一个组件。
     *
     * @param component
     *         新加入的组件。
     * @return 关联的状态栏面板。
     * @throws IllegalArgumentException
     *         如果参数{@code component}是{@code null}，或者此组件已被加入到状态栏中。
     */
    public final StatusPane addPane(
            JComponent component
    ) {
        notNull(component, "component");

        for (final StatusPane statusPane : this.statusPanes) {
            if (statusPane.getComponent() == component) {
                throw new IllegalArgumentException("component already exists");
            }
        }

        this.add(component);

        final StatusPane statusPane = new StatusPane(component);

        this.statusPanes.add(statusPane);

        return statusPane;
    }

    /**
     * 获取指定下标的状态栏面板。
     *
     * @param index
     *         下标。
     * @return 状态栏面板。
     * @throws ArrayIndexOutOfBoundsException
     *         如果指定的下标超过了合理范围。
     */
    public final StatusPane getPane(
            int index
    ) {
        validIndex(index, "index", this.statusPanes.size() - 1);

        return this.statusPanes.get(index);
    }

    /**
     * 状态栏面板。
     */
    public static class StatusPane {
        private JComponent component;
        private boolean spring;
        private Insets margin;

        public StatusPane(
                JComponent component
        ) {
            this.component = notNull(component, "component");
            this.spring = false;
            this.margin = new Insets(3, 0, 2, 0);

            updateSpring();
            updateMargin();
        }

        protected void updateSpring() {
            final Dimension size = this.component.getPreferredSize();
            if (this.spring) {
                size.width = Integer.MAX_VALUE;
            }
            this.component.setMaximumSize(size);
        }

        protected void updateMargin() {
            this.component.setBorder(combineBorders(this.component.getBorder(), createEmptyBorder(this.margin.top, this.margin.left, this.margin.bottom, this.margin.right)));
        }

        /**
         * 隐藏此面板。
         */
        public void hide() {
            this.component.setVisible(false);
        }

        /**
         * 显示此面板。
         */
        public void show() {
            this.component.setVisible(true);
        }

        /**
         * 获取面板四周的空白尺寸。
         *
         * @return 面板四周的空白尺寸。
         */
        public Insets getMargin() {
            return this.margin;
        }

        /**
         * 设置面板四周的空白尺寸。
         *
         * @param margin
         *         面板四周的空白尺寸。
         * @throws IllegalArgumentException
         *         如果参数{@code margin}
         */
        public void setMargin(
                Insets margin
        ) {
            this.margin = notNull(margin, "margin");
            updateMargin();
        }

        /**
         * 判断该面板是否自动扩展。
         *
         * @return 该面板是否自动扩展。
         */
        public boolean isSpring() {
            return this.spring;
        }

        /**
         * 设置该面板是否自动扩展。
         *
         * @param spring
         *         该面板是否自动扩展。
         */
        public void setSpring(
                boolean spring
        ) {
            this.spring = spring;
            updateSpring();
        }

        /**
         * 获得此面板关联的组件。
         *
         * @return 此面板关联的组件。
         */
        public final JComponent getComponent() {
            return this.component;
        }
    }
}
